<template>
  <div class="wy-grid">
    <div class="mask-container" v-if="isMask"></div>
    <vxe-grid
      ref="xGrid"
      height="auto"
      auto-resize
      :highlight-current-row="true"
      :loading="loading"
      :toolbar-config="{
        ...defaultToolbar,
        customConfig: {
          immediate: true,
          isFooter: false,
          icon: 'wy-icon wy-lieshezhi'
        },
        slots: {
          buttons: 'toolbar_buttons'
        }
      }"
      :loading-config="{ text: $srv.getI18nByPath('vxe.grid.loading') }"
      :row-config="{
        useKey: true
      }"
      :menu-config="getContext()"
      :checkbox-config="checkboxConfig"
      :edit-config="editConfig"
      :show-header="tableStyle.showHeader"
      :show-footer="tableStyle.showFooter"
      :columns="tableColumns"
      :data="treeLocalData"
      :border="true"
      :tree-config="treeConfig"
      @menu-click="contextMenuClickEvent"
      @current-change="handleCurrentRowChange"
      @radio-change="handleCurrentRowChange"
      @checkbox-change="handleCheckboxChange"
      @checkbox-all="handleCheckboxChange"
    >
      <!-- toolbar -->
      <template v-slot:toolbar_buttons>
        <o-toolbar :config="toolbar" @commitEvent="commitEvent"></o-toolbar>
      </template>
    </vxe-grid>
    <o-modal
      v-model="isOpenEditPanel"
      :title="editPanelTitle"
      :size="[300, 500]"
      :mask="true"
      :tap-close="true"
      :show-footer="true"
      :keep-alive="true"
      @on-ok="confirmEditPanel"
    >
      <div class="edit-panel" slot="content">
        <o-base-form ref="modifyForm" :mode="1"></o-base-form>
      </div>
    </o-modal>
  </div>
</template>

<script lang="ts">
import oBaseForm from '@/components/base/grid/o-base-form/index.vue';
import oModal from '@/components/base/modal/o-modal/index.vue';
import { Grid, MenuFirstOption, RowInfo } from 'vxe-table';
import vxeConfig from '../configs/vxetable';
import { I_cmd, ifs, T_cmd, T_srv, ts, Tsrv, vue } from './config';
import oToolbar from './toolbar.vue';

@T_srv.comp({
  components: {
    oToolbar,
    oModal
  }
})
export default class oTreeGrid extends vue {
  /**
   * refs
   */
  $refs!: {
    xGrid: Grid;
    modifyForm: oBaseForm;
  };

  @T_srv.watch('$i18n.locale')
  watchI18nData() {
    this.treeLocalData = Tsrv.utils.toArrayTree(this.localData, {
      parentKey: this.childField
    });
  }

  /**
   * props
   */
  @T_srv.prop({
    required: false
  })
  config!: any;

  @T_srv.prop({ default: 0, required: false }) readonly mode!: number;

  /* 父组件compBoxInfo */
  @T_srv.prop({
    required: false,
    type: Object,
    default: null
  })
  compBoxInfo: ifs.I_compBoxInfo;

  private grid!: Grid;

  // 表格实例
  /* 功能变量 */
  private loading: boolean = false;

  // 是否在加载
  private current: any = {
    rowIndex: 0,
    row: {}
  };

  private isNavMode: boolean = true;

  // 是否为导航模式
  private isMutiSelect: boolean = false;

  // 是否为多选
  private isStepTree: boolean = false;

  private isLazy: boolean = false;

  private isFooterRemote: boolean = true;

  // 是否使用服务器footer数据
  private hasTotal: boolean = true;

  /* 自定义预设 */
  // 标识，用来请求/修改数据
  private name: string = 'oTreeGrid';

  private G_compName: string = this.name;

  /* 组件箱信息对象 */
  private GT_compBoxInfo: ifs.I_compBoxInfo;

  /* 组件箱对象 */
  private GT_compBox: ifs.I_compBox;

  /* 组件箱识别ID */
  private G_compID: string;

  public isMask: boolean = false;

  // 名称
  // 默认配置
  private checkboxConfig: any = null;

  /* 指挥部 */
  private GT_command: I_cmd = new T_cmd();

  // 复选框的配置
  private treeConfig: any = {
    // [vxe-table v3.7.0] 参数 "tree-config.children" 已废弃，请使用 "tree-config.childrenField"
    // children: 'children',
    childrenField: 'children',
    expandAll: false,
    indent: 20,
    accordion: false,
    // [vxe-table v3.7.0] 参数 "tree-config.line" 已废弃，请使用 "tree-config.showLine"
    // line: true,
    showLine: true,
    lazy: this.isLazy,
    // hasChild: 'HASCHILD', // 已废弃
    hasChildField: 'HASCHILD',
    expandRowKeys: [null],
    loadMethod: this.loadChildrenMethod
  };

  // tree的配置
  private editConfig: any = null;

  // 变换配置
  private tableStyle: any = null;

  // 样式
  private tableColumns: any = null;

  // 字段
  private messageConfig: any = null;

  // 信息的配置
  private tableDataSetting: any = null;

  // 数据配置
  private tableDataSource: any = null;

  // 数据源
  private toolbar: any = null;

  // private queryParamsNavMode: any = null;

  private GT_qryParams: ifs.I_getTreeDataArg;

  // 导航模式的sql语句
  private storedTableColumns: any = null; // tablecolumn缓存

  private keyField: string = '';

  private childField = null;

  private modifyForm = null;

  // 自带tool，全屏和显示
  private defaultToolbar: any = {
    id: 'toolbar',
    zoom: true,
    custom: {
      storage: true
    }
  };

  private localData = [];

  // 本地数据
  private treeLocalData: any = []; // 本地树形数据

  private columnInfo: any = {};

  private listenType: string = 'default';

  private isOpenEditPanel: boolean = false;

  private editPanelType: string = '';

  private editPanelData = {};

  private editPanelOData = {};

  private editPanelTitle: string = '';

  private reportID = null;

  private funName: string = '';

  created() {
    // 如果父组件没有传参，那就产生一个
    this.GT_compBoxInfo = Tsrv.getCompInfo(this.compBoxInfo);
    this.G_compID = this.GT_compBoxInfo.compID;
    this.GT_compBox = this.GT_compBoxInfo.TcompBox;
    this.GT_command.init(this, this.GT_compBoxInfo);
    this.funName = this.config?.name || '';
    this.GT_command.newTcompCoordination(this.config);
    this.GT_qryParams = new ts.T_getTreeDataArg();
    if (this.mode === 0) {
      this.name = this.config.name; // 名称
      // 变换配置
      this.tableStyle = this.config.tableStyle;
      this.isNavMode = this.tableStyle.mode === 'nav';
      this.toolbar = vxeConfig.getToolbarConfig(
        this.config.toolbar,
        'treegrid'
      );
      this.tableDataSetting = this.config.tableDataSetting; // 数据设置
      this.messageConfig = this.config.messageConfig; // 消息设置
      this.tableDataSource = this.config.tableDataSource;
      // toolbar
      this.defaultToolbar = this.config.tableStyle.showToolbar
        ? this.toolbar.default
          ? this.defaultToolbar
          : {}
        : false;
      // editable，不是导航模式，且开启了编辑
      if (this.tableDataSetting.editable && !this.isNavMode) {
        this.editConfig = {
          trigger: 'click',
          mode: 'cell',
          showStatus: true
        };
      }
    } else {
      this.tableStyle = {
        border: false,
        showHeader: true,
        showFooter: false
      };
      this.toolbar = vxeConfig.getToolbarConfig({}, 'treegrid');
      this.tableDataSetting = {};
      this.messageConfig = {
        emitActions: {}
      };
    }
  }

  mounted() {
    this.grid = this.$refs.xGrid;
    /* 向父组件发送实例 */
    this.GT_compBox.addCompMergeName(this.G_compID, this.G_compName, this);
    this.$emit('compBoxInfo', this.GT_compBoxInfo);
    /* 最终应用组件向外抛出引用实例,以供应用间调用 */
    Tsrv.compBox.addCompMergeName(
      Tsrv.compBox.getDefGUID(), // 全局compBox
      this.funName,
      this
    );
    if (this.mode === 0) {
      this.modifyForm = this.$refs.modifyForm as oBaseForm;

      this.listenType = this.config['listenType'] || 'default';

      // 配置数据源
      if (this.isNavMode) {
        // 导航模式
        this.transformSource(this.config.tableDataSource);
        this.toolbar.selectMode.value = this.isMutiSelect;
      } else {
        // 非导航模式
        this.storedTableColumns = this.config.tableColumns;

        this.tableColumns = this.transformColumns(this.storedTableColumns); // 转换column
      }

      if (this.config?.messageConfig?.custDefListener?.coordination) {
        this.$bus.$on(
          this.config.messageConfig.custDefListener.coordination,
          msg => {
            this.handleListener(msg);
            this.GT_command.receEventCoordination(msg);
          }
        );
      }
      // 加载数据
      this.loadTableData();
    }
  }

  destroyed() {
    /* 注册组件销毁 */
    this.GT_compBox.removeCompMergeName(this.G_compID, this.G_compName);
    /* 最终应用组件销毁 */
    Tsrv.compBox.removeCompMergeName(Tsrv.compBox.getDefGUID(), this.funName);

    /* 如果父组件传入的compBoxInfo则删除本文件产生的引用,反之是本组件产生的ID统一删除 */
    if (Tsrv.utils.isEmpty(this.compBoxInfo)) {
      this.GT_compBox.removeCompsWithCompID(this.G_compID);
    } else {
      this.GT_compBox.removeCompsMergeName(this.G_compID, [
        `'${this.G_compName}'`
      ]);
    }
    if (this.config?.messageConfig?.custDefListener?.coordination) {
      this.$bus.$off(this.config.messageConfig.custDefListener.coordination);
    }
  }

  public setLasy(value: boolean) {
    this.isLazy = value;
  }

  public setReportID(id: number) {
    this.reportID = id;
    // this.queryParamsNavMode['reportPlanId'] = this.reportID;
    this.GT_qryParams.reportPlanId = id;
  }

  public setTreeConfig(property: string, value: any) {
    this.treeConfig[property] = value;
  }

  public setToolbar(toolbar: any) {
    if (toolbar === false) {
      this.toolbar = null;
      this.defaultToolbar = false;
    } else {
      this.toolbar = vxeConfig.getToolbarConfig(toolbar, 'treegrid');
      this.defaultToolbar = this.defaultToolbar;
      this.toolbar.delete.isDisable = true;
    }
  }

  public setDataSetting(setting: any, key?: any) {
    if (key) {
      this.tableDataSetting[key] = setting;
    } else {
      this.tableDataSetting = setting;
    }

    this.isFooterRemote =
      this.tableDataSetting.isFooterRemote === undefined
        ? true
        : this.tableDataSetting.isFooterRemote;
  }

  // 配置数据源
  public transformSource(source: any) {
    this.childField = Tsrv.utils.find(
      source.main.fields,
      el => el.childField === true
    )?.field;
    this.keyField = Tsrv.utils.find(
      source.main.fields,
      el => el.keyField === true
    )?.field;
    this.name = source.main.name; // table名
    // 子字段为空，则为一级导航模式，默认开启懒加载
    if (!Tsrv.utils.isEmpty(this.childField)) {
      this.firstlevelNav(source.main.fields);
      this.isStepTree = true;
    } else {
      this.multilevelNav(source.main.fields);
      this.isStepTree = false;
      this.isMutiSelect = false;
    }
  }

  // 一级导航
  private firstlevelNav(fields: Array<any>) {
    const Tfilter: ifs.I_filter = new ts.T_filter();
    const fvs: ifs.I_fv[] = [];
    fields.forEach(el => {
      if (el.filter) {
        fvs.push({ field: el.field, value: el.filter } as ifs.I_fv);
      }
    });
    this.GT_qryParams.setMode('stepTree').setTableName(this.name);
    // this.GT_qryParams.setFields(
    //   ...(fields.filter(el => el.isShow === true).map(el => el.field) as Array<
    //     string
    //   >))
    this.GT_qryParams.setFields(...fields.map(el => el.field))
      .setOptions({
        hasChild: 'HASCHILD',
        childField: this.childField,
        childValue: null,
        isLazy: this.isLazy
      })
      .setReportPlanId(null)
      .setFilter(Tfilter.parseFvs(fvs));
  }

  // 多级导航
  private multilevelNav(fields: Array<any>) {
    const Tfilter: ifs.I_filter = new ts.T_filter();
    const fvs: ifs.I_fv[] = [];
    fields.forEach(el => {
      if (el.filter) {
        fvs.push({ field: el.field, value: el.filter } as ifs.I_fv);
      }
    });
    // const objs: Array<object> = [];
    // const fvs: ifs.I_fv[] = [];
    // fields.forEach(el => {
    //   if (el.filter) {
    //     if (Tsrv.utils.isJSONString(el.filter)) {
    //       const v = JSON.parse(el.filter);
    //       Tsrv.utils.isPlainObject(v)
    //         ? objs.push(v)
    //         : fvs.push({ field: el.field, value: el.filter } as ifs.I_fv);
    //     } else {
    //       fvs.push({ field: el.field, value: el.filter } as ifs.I_fv);
    //     }
    //   }
    // });
    // let _filter: any = null;
    // const _f: object[] = [];
    // fvs.forEach(ele => {
    //   const v = Tfilter.parseEQ(ele.field, ele.value);
    //   Object.keys(v).length > 0 && _f.push(v);
    // });
    // _f.push(...objs);
    // if (_f.length === 1) {
    //   _filter = _f[0];
    // }
    // if (_f.length > 1) {
    //   _filter = Tfilter.parseAND(_f);
    // }
    //
    this.GT_qryParams.setMode('flatTree').setTableName(this.name);
    this.GT_qryParams.setFields(this.keyField)
      .setOptions(null)
      .setReportPlanId(null)
      .setFilter(Tfilter.parseFvs(fvs));
    // .setFilter(_filter);
  }

  // 配置字段
  public transformColumns(columns: any) {
    const vxeColumns: any = [];
    columns.forEach((el: any) => {
      if (el.isShow) {
        vxeColumns.push(this.getClmsWithConfig(el));
      }
    });
    if (this.isMutiSelect || this.tableDataSetting.editable) {
      this.checkboxConfig = {
        labelField: 'id',
        highlight: false,
        checkStrictly: false
      };
      vxeColumns.unshift({
        type: 'checkbox',
        treeNode: true
      });
    } else {
      vxeColumns.unshift({
        field: 'id',
        title: 'ID',
        treeNode: true
      });
    }
    return vxeColumns;
  }

  public getClmsWithConfig(e: any) {
    const field = e.field;
    // 设置字段名称、翻译、可排序
    interface TableColumn {
      field?: string;
      title?: string;
      editRender?: any;
      formatter?: any;
      align?: any;
    }
    const column: TableColumn = {};
    column.field = field;
    column.title = e.field;
    if (e.type) {
      // 获取数据类型和长度
      let length = e.type.match(/\(([^)]*)\)/);
      let type = e.type;
      let formatType = '';
      if (length != null) {
        type = type.replace(/\(.*?\)/, '');
        length = length[1];
      }
      // 整合类型
      if (type === 'int' || type === 'dec' || type === 'smallint') {
        type = 'number';
        formatType = 'number';
      } else if (type === 'varchar' || type === 'text' || type === 'bigint') {
        type = 'text';
        formatType = 'text';
      }
      if (Tsrv.utils.get(e.formatter, 'type') === 'i18n') {
        type = 'i18n';
        formatType = 'i18n';
      }
      column.editRender = {
        name: '',
        props: { size: 'small' },
        autoselect: true,
        events: {},
        attrs: {}
      };
      // 如果是magicbox情况
      // m2o
      switch (formatType) {
        case 'number':
          column.editRender.props['type'] = 'number';
          column.formatter = ['numberFormatter', e.formatter];
          break;
        case 'dateTime':
          column.editRender.props['type'] = 'datetime';
          column.editRender.props['format'] = 'yyyy-MM-dd HH:mm:ss';
          break;
        case 'i18n':
          column.formatter = 'i18nFormatter';
          break;

        default:
          break;
      }
      switch (type) {
        case 'number':
          column.editRender.name = 'Input';
          break;
        case 'text':
          column.editRender.name = 'Input';
          break;
        case 'dateTime':
          column.editRender.name = 'DatePicker';
          column.editRender.props['clearable'] = false;
          break;

        default:
          break;
      }
    }
    return column;
  }

  /**
   * 表格事件
   */
  // 当前行改变
  public handleCurrentRowChange(table: any) {
    this.current.row = table.row;
    this.current.rowIndex = table.$rowIndex;
    if (!(this.isNavMode && this.isMutiSelect)) {
      const row = Tsrv.utils.toTreeArray([table.row]);
      this.$emit('on-row-change', row);
      this.messageEmit('search', row);
    }
  }

  // 当前选择改变
  public handleCheckboxChange(table: any) {
    this.$emit('on-row-change', table.records);
    this.messageEmit('search', table.records);
  }

  // 通过事件toID获取要search的功能名
  private getFunNameByToID(toID: string): string {
    for (const o of this.config.messageConfig.emitActions.search) {
      if (o.toID !== toID) {
        continue;
      } else {
        return o.sourceToID;
      }
    }
    return '';
  }

  /**
   * 发送外部事件
   */
  public messageEmit(type: string, row: any) {
    const receivers = this.messageConfig.emitActions[type] || [];
    receivers.forEach((item: any) => {
      item.msg.listenType = this.listenType;
      if (type === 'search') {
        item.msg.content.val = Tsrv.utils.map(
          row,
          el => el[item.msg.content.ikey]
        );
        const toID = item.toID.toString();
        // option
        // if (item.msg.content.val.length === 1) {主表选中哪一级，子表新增就填写哪一级
        const option: any = {
          autoCompleteInfo: {
            key: item.msg.content.val[0],
            // table: toID,
            sourceToID: toID, // 原来toID采用功能名，功能配置改为唯一码，这里是记录唯一功能码
            table: this.getFunNameByToID(toID), // toTable
            fromTable: '',
            data: row[0]
          }
        };
        if (this.columnInfo[item.msg.content.ikey]) {
          if (this.columnInfo[item.msg.content.ikey].m2o) {
            option.autoCompleteInfo['field'] = item.msg.content.ikey;
            option.autoCompleteInfo['m2oField'] = this.columnInfo[
              item.msg.content.ikey
            ].m2o;
          } else if (this.columnInfo[item.msg.content.ikey].slc) {
            option.autoCompleteInfo['field'] = item.msg.content.ikey;
            option.autoCompleteInfo['slcField'] = this.columnInfo[
              item.msg.content.ikey
            ].slc;
          }
        }
        option.autoCompleteInfo['pidField'] = item.msg.content.ukey;
        item.msg['option'] = option;
        // }
        if (this.listenType === 'default') {
          this.$bus.$emit(toID, item.msg);
        } else {
          this.$mbus.$emit(toID, item.msg);
        }
      }
    });
  }

  /**
   * 行为命令
   */
  public commitEvent(val: string, params: any) {
    switch (val) {
      case 'expand_all':
        this.grid.setAllTreeExpand(true);
        break;
      case 'contract_all':
        this.grid.clearTreeExpand();
        break;
      case 'selectMode':
        this.selectHandle(params);
        break;
      case 'reload':
        this.loadTableData();
        break;
      case 'on-search':
        this.onSearch(params);
        break;
      case 'on-search-change':
        this.onSearch(params.data);
        break;
      default:
        break;
    }
  }

  private selectHandle(p: boolean) {
    if (p) {
      this.isMutiSelect = true;
      this.tableColumns = this.isNavMode
        ? this.transformResultToColumns(this.storedTableColumns)
        : this.transformColumns(this.storedTableColumns);
    } else {
      this.isMutiSelect = false;
      this.tableColumns = this.isNavMode
        ? this.transformResultToColumns(this.storedTableColumns)
        : this.transformColumns(this.storedTableColumns);
      this.grid.clearCheckboxRow();
    }
  }

  private onSearch(val: string) {
    if (Tsrv.utils.noValue(val)) {
      this.grid.setAllCheckboxRow(false);
      return;
    }
    const regex = new RegExp(val, 'g');
    const findRows: Array<RowInfo> = [];
    this.searchData(this.grid.getData(), regex, findRows);
    this.grid
      .setAllTreeExpand(true)
      .then(el => {
        this.selectHandle(true);
        if (!Tsrv.utils.noValue(findRows)) {
          this.grid
            .setAllCheckboxRow(false)
            .then(e => {
              this.grid.setCheckboxRow(findRows, true);
              this.$emit('on-row-change', this.grid.getCheckboxRecords());
              this.messageEmit('search', this.grid.getCheckboxRecords());
            })
            .catch(err => {
              console.error(err);
            });
        }
      })
      .catch(err => {
        console.error(err);
      });
  }

  private searchData(rows: RowInfo[], regexp: RegExp, findRows: RowInfo[]) {
    for (const row of rows) {
      for (const k of Object.keys(row)) {
        if (k === '_XID' || k === 'children' || k === 'undefined') {
          continue;
        }
        // if (`${row[k]}`.match(regexp)) {
        if (`${row[k]}`.match(regexp) && k.indexOf(this.keyField) > -1) {
          findRows.push(row);
        }
      }
      if (row['children'].length > 0) {
        this.searchData(row['children'], regexp, findRows);
      }
    }

    return null;
  }

  // 导航模式，将结果转换为列配置
  public transformResultToColumns(result: any) {
    // 存储备份数据
    this.storedTableColumns = Tsrv.utils.clone(result, true);
    const keyArr = Object.keys(result);
    // 需替换的原字段，需要替换的主字段
    const replaceArr: string[] = [];
    let repalceKeyField = this.keyField;
    this.columnInfo = {};
    keyArr.forEach(el => {
      // 存在m2o或存在下拉
      if (el.indexOf('|') > -1) {
        const elArr = el.split('|');
        replaceArr.push(elArr[1]);
        if (elArr[1] === this.keyField) repalceKeyField = el;
        if (this.columnInfo[elArr[1]]) {
          this.columnInfo[elArr[1]][elArr[0]] = el;
        } else {
          this.columnInfo[elArr[1]] = {
            m2o: undefined,
            slc: undefined
          };
          this.columnInfo[elArr[1]][elArr[0]] = el;
        }
      }
    });

    // 移除非相关列
    Tsrv.utils.remove(
      keyArr,
      el =>
        el === 'id' ||
        el === repalceKeyField ||
        el === '_XID' ||
        el === 'parentId' ||
        el === 'children' ||
        el === 'HASCHILD' ||
        el === this.childField ||
        replaceArr.indexOf(el) > -1
    );
    // 设置其他列属性，默认i18n转换
    const vxeColumns: any = Tsrv.utils.map(keyArr, el => {
      let title = el;
      // 如果存在m2o或存在下拉，则显示名为原字段，但数据为转换过字段的数据
      if (el.indexOf('|') > -1) title = el.split('|')[1];

      return {
        field: el,
        title,
        formatter: 'i18nFormatter'
      };
    });
    // 导航模式开启多选，或者非导航模式开启编辑，配置复选框
    //! !!!!多选框字段无法应用i18n
    if (
      (this.isNavMode && this.isMutiSelect) ||
      (!this.isNavMode && this.tableDataSetting.editable)
    ) {
      this.checkboxConfig = {
        labelField: repalceKeyField,
        highlight: false,
        checkStrictly: false
      };
      vxeColumns.unshift({
        type: 'checkbox',
        treeNode: true
      });
      this.grid.data.forEach(el => {
        el[repalceKeyField] = Tsrv.getI18nBySrv(el[repalceKeyField]);
      });
    } else {
      // 单选模式，将主字段放在首位
      vxeColumns.unshift({
        field: repalceKeyField,
        title: this.keyField,
        formatter: 'i18nFormatter',
        treeNode: true
      });
    }
    return vxeColumns;
  }

  // 导航模式，懒加载子节点
  // eslint-disable-next-line consistent-return
  public loadChildrenMethod({ row }: { row: any }) {
    if (this.isNavMode) {
      return new Promise(resolve => {
        if (
          !row.children ||
          row.children === null ||
          row.children.length === 0
        ) {
          this.loading = true;
          // this.queryParamsNavMode.options.childValue = row.id;
          this.GT_qryParams.options['childValue'] = row.id;

          this.GT_qryParams.setDbType('mysql');
          // this.GT_qryParams.setDbType(this.config.dbType);
          Tsrv.standardPostReq<ifs.I_setDataRes<any>, ifs.I_getTreeDataArg>(
            this.GT_qryParams
          ).then(res => {
            const [resp, msg] = res;
            if (!resp.success) {
              this.$msg(resp.msg);
            }
            msg && this.$msg(msg);
            this.loading = false;
            resolve(resp.data.rows);
          });
        } else {
          resolve(row.children);
        }
      });
    }
  }

  public setHasTotal(value: boolean) {
    this.hasTotal = value;
  }

  private setZeroNode(rows: any) {
    if (this.isStepTree) {
      rows.forEach((el: any, idx: any) => {
        if (el[this.childField] === 0) el[this.childField] = null;
      });
    }
  }

  public addVIDToData(rows: any) {
    if (!this.isStepTree) {
      rows.forEach((el: any, idx: any) => {
        if (!el.id) el.id = idx;
      });
    } else {
      const rootNode = {
        HASCHILD: rows.length === 0 ? 1 : rows.length,
        id: null
      };
      // rootNode[this.keyField] = "全部";
      rootNode[this.keyField] = Tsrv.getI18nByPath('oTreeGrid.all');
      rootNode[this.childField] = undefined;
      rows.unshift(rootNode);
    }
    return rows;
  }

  // 加载数据
  public loadTableData() {
    // 如果是导航模式
    if (this.isNavMode) {
      this.loading = true;
      if (this.isStepTree) {
        // this.queryParamsNavMode.options.childValue = null;
        this.GT_qryParams.options['childValue'] = null;
      }

      // this.GT_qryParams.setDbType('mysql');
      this.GT_qryParams.setDbType(this.config.dbType);
      Tsrv.standardPostReq<ifs.I_setDataRes<any>, ifs.I_getTreeDataArg>(
        this.GT_qryParams
      ).then(res => {
        const [resp, msg] = res;
        msg && this.$msg(msg);
        if (!resp.success) {
          this.$msg(resp.msg);
        }
        this.loading = false;
        if (resp.success) {
          const data = resp.data;
          if (data && Array.isArray(data.rows) && data.rows.length > 0) {
            this.setZeroNode(data.rows);
            this.tableColumns = this.transformResultToColumns(data.rows[0]); // 导航模式内容转列
            this.localData = this.hasTotal
              ? this.addVIDToData(data.rows)
              : data.rows;
            for (let i = 0; i < this.localData.length; i++) {
              const el = this.localData[i];
              Object.keys(el).forEach(key => {
                if (key.indexOf('|') > -1) {
                  el[key] = Tsrv.getI18nBySrv(el[key]);
                }
              });
            }
            // this.grid.setCurrentRow(this.localData[0]); // 设置当前选中行
            let currRowIdx: number = 0;
            if (this.current.rowIndex === this.localData.length) {
              currRowIdx = this.localData.length - 1;
              this.grid.setCurrentRow(this.localData[currRowIdx]);
            } else {
              currRowIdx = this.current.rowIndex;
              this.grid.setCurrentRow(this.localData[this.current.rowIndex]);
            }

            this.treeLocalData = Tsrv.utils.toArrayTree(this.localData, {
              parentKey: this.childField
            });
            if (this.isStepTree) {
              this.$nextTick(() => {
                this.grid.setTreeExpand([this.treeLocalData[0]], true); // 展开第一层
                const row = Tsrv.utils.toTreeArray([this.treeLocalData[0]]);
                this.$emit('on-row-change', row);
                this.messageEmit('search', row); // 发出选中信息
              });
            } else {
              // this.$emit('on-row-change', [this.treeLocalData[0]]);
              // this.messageEmit('search', [this.treeLocalData[0]]); // 发出选中信息
              this.$emit('on-row-change', [this.treeLocalData[currRowIdx]]);
              this.messageEmit('search', [this.treeLocalData[currRowIdx]]); // 发出选中信息
            }
            // 处理字段隐藏
            this.setHideFields();
          }
        }
      });
    }
  }

  /**
   * 右键菜单
   */
  public contextMenuClickEvent({ menu, row }: { menu: any; row: any }) {
    switch (menu.code) {
      case 'expand':
        this.grid.setTreeExpand([row], true);
        break;
      case 'contract':
        this.grid.setTreeExpand([row], false);
        break;
      case 'insertLevel':
        this.openEditPanel('insertLevel', row);
        break;
      case 'insertChild':
        this.openEditPanel('insertChild', row);
        break;
      case 'remove':
        this.delete(row);
        break;
      case 'edit':
        this.openEditPanel('edit', row);
        break;

      default:
        break;
    }
  }

  private delete(row: any) {
    if (this.loading === false) {
      // 多个
      const ids: any = [];
      this.getIds(row, ids);

      const delRec = new ts.T_ctdDelRec();
      const filter = JSON.parse(`{"id":{"$in":[${ids}]}}`);
      delRec.setFilter(filter);
      delRec.setRule({} as ifs.I_rule);

      const ctd = new ts.T_ctdArg();
      ctd
        .setTableName(this.name)
        .setDbType(this.GT_qryParams.getDbType())
        .setRule({} as ifs.I_rule)
        .setDelRec(delRec);

      this.saveEditPanel(ctd)
        .then(() => {
          this.loadTableData();
          this.isOpenEditPanel = false;
        })
        .catch(() => {
          // this.$msg("删除失败");
          this.$msg(Tsrv.getI18nByPath('oTreeGrid.failedtodelete'));
        });
    }
  }

  /**
   * @description 获取所有id
   * @param {Object} obj
   * @param {Array} arr
   */
  private getIds(obj, arr) {
    if (obj.id) {
      arr.push(`"${obj.id}"`);
    }

    if (obj.children) {
      for (let i = 0; i < obj.children.length; i++) {
        this.getIds(obj.children[i], arr);
      }
    }
  }

  private openEditPanel(type: string, row: any) {
    this.editPanelOData = row;
    this.editPanelData = Tsrv.utils.clone(row, true);
    this.editPanelType = type;
    this.isOpenEditPanel = true;
    this.editPanelTitle = Tsrv.getI18nByPath(`vxe.menu.${type}`).toString();
    this.loadFunConfig(this.name).then((columns: any) => {
      if (columns) {
        const fields = this.tableDataSource.main.fields.map(el => el.field);
        columns.forEach(el => {
          if (fields.indexOf(el.field) < 0) {
            el.isShow = false;
          }
        });
        this.modifyForm.setColumns(this.modifyForm.transformColumns(columns));
        if (type === 'insertLevel') {
          this.modifyForm.clearFormData().then(() => {
            this.modifyForm.setFieldValue(
              this.childField,
              this.editPanelData[this.childField]
            );
          });
        } else if (type === 'insertChild') {
          this.modifyForm.clearFormData().then(() => {
            this.modifyForm.setFieldValue(
              this.childField,
              this.editPanelData['id']
            );
          });
        } else if (type === 'edit') {
          this.modifyForm.clearFormData().then(() => {
            this.modifyForm.setFormData(this.editPanelData);
          });
        }
      }
    });
  }

  private confirmEditPanel() {
    if (this.loading === false) {
      if (
        this.editPanelType === 'insertLevel' ||
        this.editPanelType === 'insertChild'
      ) {
        const insertData: any = this.modifyForm.getData();
        const insRec = new ts.T_ctdInsRec();
        insRec
          .setScope(null)
          .setBaseDataGeneral({} as ifs.I_rule, {}, ...insertData);

        const saveData = new ts.T_ctdArg();
        saveData
          .setTableName(this.name)
          .setDbType(this.GT_qryParams.getDbType())
          .setRule({} as ifs.I_rule)
          .setInsRec(insRec);
        this.saveEditPanel(saveData)
          .then(() => {
            this.loadTableData();
            this.isOpenEditPanel = false;
          })
          .catch(() => {
            // this.$msg("保存失败");
            this.$msg(Tsrv.getI18nByPath('oTreeGrid.savefailed'));
          });
      } else if (this.editPanelType === 'edit') {
        const updateData: any = this.modifyForm.getUpdateData(true);
        const updRec = new ts.T_ctdUpdRec();
        updRec.setData(
          {},
          { id: this.modifyForm.formID },
          // {},
          {} as ifs.I_rule,
          ...updateData
        );
        const saveData = new ts.T_ctdArg();
        saveData
          .setTableName(this.name)
          .setDbType(this.GT_qryParams.getDbType())
          .setRule({} as ifs.I_rule)
          .setUpdRec(updRec);
        this.saveEditPanel(saveData)
          .then(() => {
            this.loadTableData();
            this.isOpenEditPanel = false;
          })
          .catch(() => {
            // this.$msg("保存失败");
            this.$msg(Tsrv.getI18nByPath('oTreeGrid.savefailed'));
          });
      }
    }
  }

  private saveEditPanel(saveData: any) {
    return new Promise((resolve, reject) => {
      // 保存
      this.loading = true;
      Tsrv.batRows(saveData).then(resp => {
        const [status, res, msg] = resp;
        if (status) {
          // 保存成功后刷新
          this.loading = false;
          resolve(true);
        } else {
          this.loading = false;
          reject();
        }
      });
    });
  }

  private loadFunConfig(field) {
    return new Promise(resolve => {
      this.$store
        .dispatch('getLayoutConfigAsync', {
          funid: null,
          field,
          type: 'component'
        })
        .then(res => {
          if (res) {
            const config = Tsrv.utils.clone(res.current, true);
            resolve(config.config.tableColumns);
          } else {
            resolve(false);
          }
        });
    });
  }

  public getContext() {
    const headerMenus: MenuFirstOption = [];
    const bodyMenus: MenuFirstOption = [
      [
        {
          code: 'expand',
          name: Tsrv.getI18nByPath('vxe.menu.expand'),
          prefixIcon: 'ivu-icon ivu-icon-ios-folder-open-outline',
          visible: true,
          disabled: false
        },
        {
          code: 'contract',
          name: Tsrv.getI18nByPath('vxe.menu.contract'),
          prefixIcon: 'ivu-icon ivu-icon-ios-folder-outline',
          visible: true,
          disabled: false
        },
        {
          code: 'insertLevel',
          name: Tsrv.getI18nByPath('vxe.menu.insertLevel'),
          prefixIcon: 'wy-icon wy-insert',
          visible: !!this.childField,
          disabled: !this.childField
        },
        {
          code: 'insertChild',
          name: Tsrv.getI18nByPath('vxe.menu.insertChild'),
          prefixIcon: 'wy-icon wy-insert',
          visible: !!this.childField,
          disabled: !this.childField
        },
        {
          code: 'remove',
          name: Tsrv.getI18nByPath('vxe.menu.remove'),
          prefixIcon: 'ivu-icon ivu-icon-ios-remove-circle-outline',
          visible: !!this.childField,
          disabled: !this.childField
        },
        {
          code: 'edit',
          name: Tsrv.getI18nByPath('vxe.menu.edit'),
          prefixIcon: 'wy-icon wy-bianji',
          visible: !!this.childField,
          disabled: !this.childField
        }
      ]
    ];
    const footerMenus: MenuFirstOption = [];
    return {
      header: { options: headerMenus },
      body: { options: bodyMenus },
      footer: { options: footerMenus }
    };
  }

  private setHideFields() {
    const hideFields = this.config.tableDataSource.main.fields
      .filter(el => el.isShow === false)
      .map(ele => ele.field);
    setTimeout(() => {
      hideFields.forEach(hineField => {
        const fields: Array<string> = [];
        for (const f of this.tableColumns) {
          if (f.field === hineField) {
            fields.push(hineField);
            break;
          }
          if (/^m2o/.test(f.field)) {
            const m2oDet = Tsrv.utils.splitM2OField(f.field);
            if (!Tsrv.utils.noValue(m2oDet?.field)) {
              if (m2oDet.field === hineField) {
                fields.push(f.field);
                break;
              }
            }
          }
        }
        fields.forEach(hf => {
          this.grid.hideColumn(this.grid.getColumnByField(hf));
        });
      }, 0);
    });
  }

  private handleListener(msg: any) {
    if (msg?.action?.toolbar === 'refresh' || msg?.action?.toolbar === 'save') {
      // 加载数据
      // msg.formComp.funName
      const nextCompName = Object.keys(
        this.messageConfig.eventGroup[''].children[0]
      )[0];
      if (nextCompName === msg?.fromComp.funName) {
        this.loadTableData();
      }
    }
  }
}
</script>

<style scoped lang="scss">
.wy-grid {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: auto;
  background-color: #fff;
}
.wy-grid ::v-deep .vxe-toolbar.size--mini {
  padding: 0;
  background-color: var(--treegrid-toolbar-bg-color);
}
</style>
